﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Forms;
using Bonesoft.Forms.Estoque;
using Business;
using Business.Dicionary;
using Business.Entity.Contabil.Pessoa;
using Business.Entity.Contabil.Pessoa.SubClass.Usuario.ClassesRelacionadas;
using Business.Entity.Estoque.Produto;
using Business.Entity.Estoque.Produto.ClassesRelacionadas;
using Business.Entity.Fiscal;
using Business.Entity.Fiscal.ClassesRelacionadas;
using Business.Entity.Sped;
using Business.Entity.Vendas.Pedido.ClassesRelacionadas;
using Business.Forms;
using Business.Seguranca;
using Business.Validation;
using DevExpress.XtraEditors;
using MessageBox = System.Windows.MessageBox;

namespace Bonesoft.Forms.Fiscal
{
    public partial class FormNotaFiscalEntrada : FormDefault, IForm
    {
        private FormProduto FormEditProduto { get; set; }
        private Produto ProdutoSelecionado { get; set; }
        private ProdutoNotaFiscal ProdutoAtual { get; set; }
        public FormNotaFiscalEntrada()
        {
            InitializeComponent();
            ProdutoRepository.Session = NotaFiscalRepository.GetSession();
            ncmBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<Ncm>().List();
            cSTBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<CST>().List();
            cFOPBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<CFOP>().List();
            unidadeBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<Unidade>().List();
            formaPagamentoBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<FormaPagamento>().List();
            var pessoas = NotaFiscalRepository.GetSession().CreateCriteria<Pessoa>().List();
            destinatarioBindingSource.DataSource = pessoas;
            transportadoraBindingSource.DataSource = pessoas;
            naturezaInternaBindingSource.DataSource = NotaFiscalRepository.GetSession().CreateCriteria<NaturezaInterna>().List();
            modeloNotaFiscalDicionaryBindingSource.DataSource = new ModeloNotaFiscalDicionary();
            notaFiscalBindingSource.DataSource = new NotaFiscal();
            CalculaNota();
            InitFocusControl = cboNaturezaInterna;
            FormEditProduto = new FormProduto();
            cmdNovoProduto.Enabled = false;

        }

        public object Save()
        {
            if (!Validate().HasError)
            {

                var nf = (NotaFiscal) CurrentObject;
                foreach (ProdutoNotaFiscal prodNf in nf.Produtos)
                {
                    prodNf.NotaFiscal = nf;
                }
                NotaFiscalRepository.Save(nf);
            }
            return CurrentObject;
        }

        public void Update(object entity)
        {
            notaFiscalBindingSource.DataSource = entity;
            produtosBindingSource.DataSource = ((NotaFiscal) entity).Produtos;
            pagamentoBindingSource.DataSource = ((NotaFiscal) entity).Pagamento;
            ShowDialog();
        }

        public bool Delete(object entity)
        {
            CurrentObject = entity;
            NotaFiscalRepository.Delete((NotaFiscal)entity);
            return true;
        }

        public object CurrentObject
        {
            get
            {
                try
                {
                    notaFiscalBindingSource.EndEdit();
                    if (produtosBindingSource.DataSource == null)
                    {
                        produtosBindingSource.DataSource = new List<ProdutoNotaFiscal>();
                    }
                    foreach (NotaFiscalPagamento pag in pagamentoBindingSource)
                    {
                        pag.NotaFiscal = (NotaFiscal) CurrentObject;
                    }
                    ((NotaFiscal)notaFiscalBindingSource.DataSource).Produtos = (IList<ProdutoNotaFiscal>)
                        produtosBindingSource.DataSource;
                    return notaFiscalBindingSource.DataSource;
                }
                catch (Exception)
                {
                    return null;
                }

            }
            set
            {
                notaFiscalBindingSource.DataSource = value;
            }
        }

        public PermissaoForm Permissao
        {
            get
            {
                return SegurancaUtils.GetPermissaoForm(Name);
            }
        }

        public EntityValidationResult Validate()
        {
            var nota = (NotaFiscal)CurrentObject;
            var result = DataValidation.ValidateEntity(nota);

            foreach (var prod in nota.Produtos)
            {
                foreach (var error in DataValidation.ValidateEntity(prod).ValidationErrors)
                {
                    result.ValidationErrors.Add(error);
                }

            }
            return result;
        }

        public void Reload()
        {

        }

        public void Cancel()
        {
            DialogResult = DialogResult.Cancel;
            Close();

        }

        public object New()
        {
            var nf = new NotaFiscal();
            nf.Entrada = true;
            nf.Produtos = new List<ProdutoNotaFiscal>();
            nf.Pagamento = new List<NotaFiscalPagamento>();
            produtosBindingSource.DataSource = nf.Produtos;
            pagamentoBindingSource.DataSource = nf.Pagamento;
            CurrentObject = nf;
            ShowDialog();
            if (nf.Id == 0)
            {
                return null;
            }
            return nf;
        }

        public XtraForm Form
        {
            get
            {
                return this;
            }
        }

        public FormState FormState { get; set; }

        private void descricaoTextEdit_Properties_Leave(object sender, EventArgs e)
        {

        }

        private void txtDescricao_Leave(object sender, EventArgs e)
        {
            if (!txtDescricao.Text.Equals(""))
            {
                ProdutoSelecionado = WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByDescricao(txtDescricao.Text));
                if (ProdutoSelecionado != null)
                {
                    ExibirProduto();
                }

            }
        }

        private void cboNcm_Leave(object sender, EventArgs e)
        {
            if (ProdutoSelecionado != null)
            {
                if (!cboNcm.EditValue.Equals(ProdutoSelecionado.NCM))
                {
                    var msg =
                        "O ncm do produto é diferênte do informado na nota fiscal.\n\n Deseja atualizar o produto.";
                    if (MessageBox.Show(msg, "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        ProdutoSelecionado.NCM = (Ncm)cboNcm.EditValue;
                        ProdutoRepository.Save(ProdutoSelecionado);
                    }
                }
            }
            cmdNovoProduto.Enabled = false;

        }

        private void txtIpi_Leave(object sender, EventArgs e)
        {
        }

        private void LimparProduto()
        {
            txtSequencia.Text = "";
            txtDescricao.Text = "";
            txtQuantidade.Text = "";
            txtValor.Text = "";
            txtIpi.Text = "";
            txtIcms.Text = "";
            ProdutoSelecionado = null;
            ProdutoAtual = null;
        }

        private bool AddProduto()
        {
            try
            {
                if (!ValidaInformacoesProduto())
                {
                    return false;
                }
                var qtd = decimal.Parse(txtQuantidade.Text.Replace(".", ","));
                var valor = decimal.Parse(txtValor.Text.Replace("R$", "").Replace(".", ",").Trim());
                ProdutoNotaFiscal prodNf = null;
                if (ProdutoAtual != null)
                {
                    prodNf = ProdutoAtual;
                }
                else
                {
                    prodNf = new ProdutoNotaFiscal();
                }

                prodNf.Sequencia = produtosBindingSource.Count + 1;
                prodNf.CFOP = (CFOP)cboCfop.EditValue;
                prodNf.CST = (CST)cboCst.EditValue;
                prodNf.NCM = (Ncm)cboNcm.EditValue;
                prodNf.Quantidade = qtd;
                prodNf.ValorUnitario = valor;
                prodNf.Produto = ProdutoSelecionado;
                prodNf.Unidade = (Unidade)cboUnidade.EditValue;
                if (!txtIcms.Text.Equals(""))
                {
                    prodNf.ValorIcms = decimal.Parse(txtIcms.Text.Replace("%", "").Trim());
                }
                if (!txtIpi.Text.Equals(""))
                {
                    prodNf.ValorIpi = decimal.Parse(txtIpi.Text.Replace("%", "").Trim());
                }


                if (ProdutoAtual == null)
                {
                    produtosBindingSource.Add(prodNf);
                    txtDescricao.Focus();
                }
                LimparProduto();
                AjustarSequencia();
                CalculaNota();
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("Erro ao incluir produto na nota fiscal.\n" + ex.Message);

            }
            return true;
        }
        private void CalculaNota()
        {
            if (CurrentObject == null)
            {
                return;
            }
            decimal total = 0;
            var n = (NotaFiscal)CurrentObject;
            foreach (ProdutoNotaFiscal prod in produtosBindingSource)
            {
                total += prod.ValorUnitario * prod.Quantidade;
            }
            
            total += n.Frete + n.OutrasDespesasAcessorias + n.Seguro - n.Desconto;
            totalTextEdit.Value = total;
        }
        private void AjustarSequencia()
        {
            int cont = 1;
            foreach (ProdutoNotaFiscal prod in produtosBindingSource)
            {
                prod.Sequencia = cont;
                cont += 1;
            }
        }

        private void txtDescricao_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyData == Keys.Delete)
            {
                if (produtosBindingSource.Current != null)
                {
                    var msg = "Deseja realmente excluir este produto?";
                    if (MessageBox.Show(msg, "Atenção", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        produtosBindingSource.Remove(produtosBindingSource.Current);
                    }
                }
            }
            if (e.KeyData == Keys.Up)
            {
                produtosBindingSource.MoveLast();
                ExibirProdutoNotaFiscal();
            }
            if (e.KeyData == Keys.Down)
            {
                produtosBindingSource.MoveNext();
                ExibirProdutoNotaFiscal();
            }
            if (e.KeyData == Keys.F9 && cmdNovoProduto.Enabled)
            {
                CadastrarProduto();
            }
        }

        private void ExibirProdutoNotaFiscal()
        {
            ProdutoAtual = (ProdutoNotaFiscal)produtosBindingSource.Current;
            if (ProdutoAtual != null)
            {
                txtSequencia.Text = ProdutoAtual.Sequencia.ToString(CultureInfo.InvariantCulture);
                txtDescricao.Text = ProdutoAtual.Produto.Descricao;
                cboNcm.EditValue = ProdutoAtual.NCM;
                cboCst.EditValue = ProdutoAtual.CST;
                cboCfop.EditValue = ProdutoAtual.CFOP;
                cboUnidade.EditValue = ProdutoAtual.Unidade;
                txtQuantidade.Text = ProdutoAtual.Quantidade.ToString(CultureInfo.InvariantCulture);
                txtValor.Text = ProdutoAtual.ValorUnitario.ToString(CultureInfo.InvariantCulture);
                txtIcms.Text = ProdutoAtual.ValorIcms.ToString(CultureInfo.InvariantCulture);
                txtIpi.Text = ProdutoAtual.ValorIpi.ToString(CultureInfo.InvariantCulture);
            }
        }

        private void ExibirProduto()
        {
            if (ProdutoSelecionado != null)
            {
                txtDescricao.Text = ProdutoSelecionado.Descricao;
                cboNcm.EditValue = ProdutoSelecionado.NCM;
            }
        }

        private void produtosBindingSource_CurrentItemChanged(object sender, EventArgs e)
        {

        }

        private void cmdNovoProduto_Click(object sender, EventArgs e)
        {
            CadastrarProduto();
        }

        private void CadastrarProduto()
        {
            var prod = FormEditProduto.New();
            if (prod != null)
            {
                ProdutoSelecionado = (Produto)prod;
                ExibirProduto();
                cboNcm.Focus();
            }
        }

        private void cmdNovoProduto_Enter(object sender, EventArgs e)
        {
            cmdNovoProduto.Enabled = true;
        }

        private void cmdAdicionarPagamento_Click(object sender, EventArgs e)
        {
            pagamentoBindingSource.Add(new NotaFiscalPagamento()
            {
                Vencimento = DateTime.Now
            });
        }

        private void txtIpi_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                if (txtSequencia.Text.Equals(""))
                {
                    if (AddProduto()) LimparProduto();
                }
                else
                {
                    if (AlterarProduto()) LimparProduto();
                }

            }
        }

        private bool AlterarProduto()
        {
            if (ValidaInformacoesProduto())
            {

                if (txtSequencia.Text.Equals(""))
                {
                    return true;
                }
                foreach (ProdutoNotaFiscal prodNf in produtosBindingSource)
                {
                    if (prodNf.Sequencia == int.Parse(txtSequencia.Text))
                    {

                        var qtd = decimal.Parse(txtQuantidade.Text.Replace(".", ","));
                        var valor = decimal.Parse(txtValor.Text.Replace("R$", "").Replace(".", ",").Trim());
                        prodNf.Sequencia = produtosBindingSource.Count + 1;
                        prodNf.CFOP = (CFOP)cboCfop.EditValue;
                        prodNf.CST = (CST)cboCst.EditValue;
                        prodNf.NCM = (Ncm)cboNcm.EditValue;
                        prodNf.Quantidade = qtd;
                        prodNf.ValorUnitario = valor;
                        prodNf.Produto = ProdutoSelecionado;
                        prodNf.Unidade = (Unidade)cboUnidade.EditValue;
                        prodNf.ValorIcms = decimal.Parse(txtIcms.Text.Replace("%", "").Trim());
                        prodNf.ValorIpi = decimal.Parse(txtIpi.Text.Replace("%", "").Trim());
                        produtosBindingSource.EndEdit();
                        txtDescricao.Focus();
                    }
                }
            }
            return true;
        }

        private bool ValidaInformacoesProduto()
        {
            if (ProdutoSelecionado == null)
            {
                System.Windows.Forms.MessageBox.Show("Informe um produto para poder continuar.");
                txtDescricao.Focus();
                return false;
            }
            if (cboNcm.EditValue == null || cboNcm.EditValue.Equals(""))
            {
                System.Windows.Forms.MessageBox.Show("Informe um NCM válido para o produto.");
                cboNcm.Focus();
                return false;
            }
            if (cboCst.EditValue == null)
            {
                System.Windows.Forms.MessageBox.Show("Informe o CST do produto.");
                cboCst.Focus();
                return false;
            }
            if (cboUnidade.EditValue == null || cboUnidade.EditValue.Equals(""))
            {
                System.Windows.Forms.MessageBox.Show("Informe a unidade de entrada do produto.");
                cboUnidade.Focus();
                return false;
            }
            if (cboCfop.EditValue == null || cboCfop.EditValue.Equals(""))
            {
                System.Windows.Forms.MessageBox.Show("Informe o CFOP do produto.");
                cboCfop.Focus();
                return false;
            }

            if (txtQuantidade.Text.Equals("") || decimal.Parse(txtQuantidade.Text.Replace(".", ",")) == 0)
            {
                System.Windows.Forms.MessageBox.Show("Informe uma quantidade válida.");
                txtQuantidade.Focus();
                return false;
            }

            if (txtValor.Text.Equals("") || decimal.Parse(txtValor.Text.Replace("R$", "").Replace(".", ",").Trim()) == 0)
            {
                System.Windows.Forms.MessageBox.Show("Informe um valor para o produto.");
                txtValor.Focus();
                return false;
            }
            return true;
        }
    }
}
